package xyz.lisys.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.RequestEntity;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import xyz.lisys.domain.dto.CustomResolverEntity;
import xyz.lisys.domain.dto.FileParamDto;
import xyz.lisys.domain.dto.UserDto;
import xyz.lisys.domain.pojo.ValidFoo;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Slf4j
@Controller
@RequestMapping("/in-parameter")
public class InParameterController {

    @Resource
    private ServletContext servletContext;

    @GetMapping("/param1")
    public String param1(@RequestParam(required = false) List<String> name) {
        // application/x-www-form-urlencoded

        if (name != null) {
            for (String s : name) {
                log.info(s);
            }
        }

        return "index";
    }

    @PostMapping("/param2")
    public String param2(@RequestBody String body) throws JsonProcessingException {
        // raw

        ObjectMapper objectMapper = new ObjectMapper();
        UserDto user = objectMapper.readValue(body, UserDto.class);
        log.info(String.valueOf(user));

        return "index";
    }

    @PostMapping("/param3")
    public String param3(@RequestBody MultipartFile file) {
        // multipart/form-data

        try {
            File resourceFile = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX);
            Path staticsPath = Paths.get(resourceFile.getPath()).resolve("statics");
            Files.createDirectories(staticsPath);
            // File staticsFile = staticsPath.toFile();
            // if (!staticsFile.exists()) {
            //     if (!staticsFile.mkdir()) {
            //         throw new RuntimeException("创建文件路径失败：" + staticsPath.toAbsolutePath());
            //     }
            // }

            Path destPath = staticsPath.resolve(Objects.requireNonNull(file.getOriginalFilename()));
            log.info(String.valueOf(destPath));

            file.transferTo(destPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return "index";
    }

    @PostMapping("/param3-1")
    public String param3_1(@RequestParam MultipartFile file, @RequestParam(required = false) String extra) {
        // multipart/form-data + 额外参数

        log.info(file.getOriginalFilename());
        log.info(extra);

        return "index";
    }

    @PostMapping("/param3-2")
    public String param3_2(@ModelAttribute FileParamDto fileParam) {
        // multipart/form-data + 整合对象

        log.info(fileParam.getFile().getOriginalFilename());
        log.info(fileParam.getExtra());

        return "index";
    }

    @GetMapping("/param4")
    public String param4(@ModelAttribute UserDto user) {
        // application/x-www-form-urlencoded + 整合对象

        log.info(user.toString());
        return "index";
    }

    @GetMapping("/param5")
    public String param5() {
        // WebApplicationContext容器获取

        // 不配置org.springframework.web.context.ContextLoaderListener spring容器是无法获取到的
        WebApplicationContext wac = (WebApplicationContext) servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        log.info(wac.toString());
        log.info(wac.getApplicationName());

        return "index";
    }

    @GetMapping(value = "/param6")
    public String param6(@RequestParam("message") @Nullable String username) {
        // RequestParam 可以设置接收参数的别名，可以与前端传入的值名称不一样

        log.info(username);
        return "index";
    }

    @GetMapping(value = "/param7")
    @ResponseBody
    public String param7(HttpServletRequest request) {
        // 获取sessionId

        return request.getSession().getId();
    }

    @PostMapping("/param8")
    public String param8(@RequestBody HashMap<String, Object> map) {
        // 获取Json入参

        String name = (String) map.get("message");
        log.info(name);
        return "index";
    }

    @PostMapping(value = "/param9", produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String param9(@ModelAttribute("user") @Valid ValidFoo user, BindingResult result) {
        // 校验参数错误结果

        if (result.hasErrors()) {
            // 返回内容含中文时候使用 StringHttpMessageConverter 字符集是 ISO-8859-1
            log.info(Objects.requireNonNull(result.getFieldError()).getDefaultMessage());
            return Objects.requireNonNull(result.getFieldError()).getDefaultMessage();
        }
        return "ok";
    }

    @GetMapping("/param10")
    @ResponseBody
    public String param10(@ModelAttribute("preToken") String token) {
        // 使用控制器增强类创建

        return token;
    }

    @GetMapping("/param11")
    @ResponseBody
    public String param11(CustomResolverEntity entity) {
        // 自定义参数解析器

        System.out.println(entity);
        return "entity";
    }

    @GetMapping("/param12")
    @ResponseBody
    public String param12(RequestEntity<Void> requestEntity) {
        // 请求实体类

        System.out.println(requestEntity.getMethod());
        System.out.println(requestEntity.getUrl());
        return "entity";
    }

    @GetMapping("/param13")
    @ResponseBody
    public String param13(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) {
        // 日期格式获取

        System.out.println(date);
        return "entity";
    }
}
